import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;

import DataModel.Evaluation;
import DataModel.Movie;
import DataModel.User;
import DecisionTree.DecisionTree;
import DecisionTree.Node;

public class Classification {

	public ArrayList<Integer> KNeighbors(int k,
			HashMap<Integer, Double> similarities) {

		ArrayList<Double> vals = new ArrayList<Double>(similarities.values());

		ArrayList<Integer> resultIndexes = new ArrayList<>();
		ArrayList<Integer> resultKeys = new ArrayList<>();

		for (int i = 0; i < k; i++) {
			Double maxVal = 0.0;
			Integer maxValIndex = 0;
			for (int j = 0; j < vals.size(); j++) {
				if (vals.get(j) > maxVal) {
					maxVal = vals.get(j);
					maxValIndex = j;
				}
			}
			resultIndexes.add(maxValIndex);
			vals.set(maxValIndex, 0.0);
		}

		int index = 0;

		for (Entry<Integer, Double> entry : similarities.entrySet()) {
			for (int m = 0; m < resultIndexes.size(); m++) {
				if (index == resultIndexes.get(m)) {
					resultKeys.add(entry.getKey());
					break;
				}
			}
			index++;
		}

		return resultKeys;
	}

	public ArrayList<Similarity> calculateSimilarity(boolean isGreedyForward) {

		ArrayList<Similarity> nullEvaluations = new ArrayList<>();
		HashMap<Integer, User> data = ReadData.getMoviesEvaluated();

		data = ReadData.getMoviesToBeEvaluated(data);
		HashMap<Integer, Movie> movies = ReadData.getMoviesWithFeatures();
		ArrayList<Integer> ignoreFeatures=new ArrayList<>();
		if(isGreedyForward==true){
			ArrayList<Integer> feat=GreedyForwardSelectionAlgorithm.greedyForwardSelection(movies);
			for(int i=0;i<movies.get(1).features.size();i++){
				boolean found=false;
				for(Integer featId : feat){
					if((featId-1) == i) found=true;
				}
				if(found==false) ignoreFeatures.add(i);
			}
		}
		double result = 0.0;

		for (Entry<Integer, User> entry : data.entrySet()) {
		
			User user = entry.getValue();
			//System.out.println("k = " + k + ", userId = " + user.userId);
			for (Evaluation unknownEvaluation : user.notEvaluatedMovies) {
			//	similarities = new HashMap<>();
	
				Movie unknown_movie = null;
				Movie any_movie = null;
				
				for (Entry<Integer, Movie> movie : movies.entrySet()) {
					if (unknownEvaluation.movieId == movie.getValue().movieId) {
						unknown_movie = movie.getValue();
						break;
					}
				}

				ArrayList<Movie> evaluatedMovies=new ArrayList<>();
				for (Entry<Integer, Movie> entry_movie : movies.entrySet()) {
					for(int i=0;i<user.evaluatedMovies.size();i++){
					if(entry_movie.getValue().movieId==user.evaluatedMovies.get(i).movieId)
					evaluatedMovies.add(entry_movie.getValue());
					}
					}
				

				DecisionTree dectree=new DecisionTree();
				if(isGreedyForward==true){
					dectree.usedFeatures.addAll(ignoreFeatures);
				}
				Node initial_root=new Node();
				initial_root.evaluatedMovies=evaluatedMovies;
				initial_root.evaluations=user.evaluatedMovies;
				dectree.buildTree(initial_root);
				Node returned_node = dectree.traverse(initial_root, unknown_movie);
				
				System.out.println("----");
				System.out.println("Final movies size = "+dectree.finalMovies.size());
				System.out.println("----");
				Similarity sim;
				if(dectree.finalEvals.size()==1){
	
					sim = new Similarity(user.userId,unknown_movie.movieId, Integer.parseInt(dectree.finalEvals.get(0).evaluation)); 
				}
				else{
					int eval=0;
					for(int i=0;i<dectree.finalEvals.size();i++){
						eval+=Integer.parseInt(dectree.finalEvals.get(i).evaluation);
					}
					eval = (int)Math.round((double)eval/(double)dectree.finalEvals.size());
					sim = new Similarity(user.userId,unknown_movie.movieId, eval); 
				}				
				
				nullEvaluations.add(sim);
			
			}
		
		}

		return nullEvaluations;
	}
}
